package iface;

import java.io.Serializable;

/**
 * Stores information about a user
 * 
 * @author Jeff
 * 
 */
public final class HvZUser implements Serializable, Message {
    private static final long serialVersionUID = 4L;
    public static final int MAX_FRESHNESS = 10;
    private Location data;
    private String username;
    private UserTypes type;
    private String phone;
    private int freshness;
    private boolean keepForever = false;

    /**
     * Constructs a new HvZUser
     * 
     * @param username
     *            the user's name
     * @param type
     *            what kind of user is this? based on UserType enum.
     * @param phone
     *            the user's phone number
     * @param loc
     *            the user's location
     */
    public HvZUser(String username, UserTypes type, String phone, Location loc) {
        this.data = loc;
        this.type = type;
        this.phone = phone;
        this.username = username;
    }

    /**
     * Constructs a new HvZUser
     * 
     * @param username
     *            the user's name
     * @param type
     *            what kind of user is this? based on UserType enum.
     * @param phone
     *            the user's phone number
     */
    public HvZUser(String username, UserTypes type, String phone) {
        this(username, type, phone, null);
    }

    /**
     * @return true if the user is a zombie, false otherwise
     */
    public boolean isZombie() {
        return type.equals(UserTypes.ZOMBIE);
    }

    /**
     * Checks whether the given user is the same as this user
     * 
     * @param other
     *            the user to compare against
     * @return true if the other user is the same, false otherwise
     */
    public boolean isSameUser(HvZUser other) {
        return username.equals(other.username) && phone.equals(other.phone);
    }

    /**
     * Returns the type that this user is.
     * 
     * @return the UserType enum that represents this user.
     */
    public UserTypes getUserType() {
        return type;
    }

    /**
     * Update this user's location
     * 
     * @param loc
     *            the location to update to
     */
    public void updateLocation(Location loc) {
        this.data = loc;
        this.freshness = MAX_FRESHNESS;
    }

    /**
     * Indicates that there is no new server location data
     * 
     * @return the freshness of this user. Higher is more recently updated
     */
    public int noLocationUpdate() {
        if (keepForever)
            return MAX_FRESHNESS;
        else
            return --this.freshness;
    }

    /**
     * @return this user's location
     */
    public Location getLocation() {
        return data;
    }

    /**
     * Changes this user into a zombie
     */
    public void killUser() {
        type = UserTypes.ZOMBIE;
    }

    /**
     * @return the user's username
     */
    public String getUsername() {
        return this.username;
    }

    /**
     * @return the user's phone number
     */
    public String getPhone() {
        return this.phone;
    }

    /**
     * Set that this user is to be kept forever, ie. no cache eviction.
     */
    public void keepForever() {
        this.keepForever = true;
    }

    /**
     * Returns a String indicating this user's state. Format: <[username],
     * [zombie/human/observer], [phone number], [location if present]>
     */
    public String toString() {
        String ret = "<" + this.username + ", " + phone + ", " + type;
        if (data != null)
            ret += ", " + data.getLat() + ", " + data.getLong() + ">";
        else
            ret += ">";
        return ret;
    }

    // (jake) added to make hash consistent for the same user
    public int hashCode() {
        return username.hashCode() ^ phone.hashCode() ^ type.hashCode();
    }
}
